package com.cloudOffice.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudOffice.constant.GlobalConstant;
import com.cloudOffice.constant.HttpConstant;
import com.cloudOffice.constant.SystemConstant;
import com.cloudOffice.execption.SystemException;
import com.cloudOffice.helper.MenuHelper;
import com.cloudOffice.mapper.SysMenuMapper;
import com.cloudOffice.mapper.SysRoleMenuMapper;
import com.cloudOffice.model.system.SysMenu;
import com.cloudOffice.model.system.SysRoleMenu;
import com.cloudOffice.service.SysMenuService;
import com.cloudOffice.vo.system.AssignMenuVo;
import com.cloudOffice.vo.system.MetaVo;
import com.cloudOffice.vo.system.RouterVo;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {
	
	@Resource
	private SysMenuMapper sysMenuMapper;
	@Resource
	private SysRoleMenuMapper sysRoleMenuMapper;
	
	@Override
	public List<SysMenu> findNodes() {
		//全部权限列表
		List<SysMenu> sysMenuList = list();
		if (CollectionUtils.isEmpty(sysMenuList)) {
			log.error("【查询菜单列表】查询结果为空");
			return null;
		}
		//构建树形数据
		return MenuHelper.buildTree(sysMenuList);
	}
	
	public void deleteId(Long id) {
		long count = count(Wrappers.<SysMenu>lambdaQuery().eq(SysMenu::getParentId, id));
		if (count > GlobalConstant.INTEGER_ZERO) {
			log.error("【删除菜单】菜单下有子菜单，不能删除");
			throw new SystemException(HttpConstant.CODE_201, SystemConstant.SYSMENU_NO_DELETED);
		}
		boolean b = removeById(id);
		log.info("删除菜单成功:{}", b);
	}
	
	/**
	 * 根据角色获取菜单权限数据
	 */
	@Override
	public List<SysMenu> findSysMenuByRoleId(Long roleId) {
		//全部权限列表
		List<SysMenu> allSysMenuList = list(Wrappers.<SysMenu>lambdaQuery().eq(SysMenu::getStatus,
				GlobalConstant.INTEGER_ONE));
		//根据角色id获取角色权限
		List<SysRoleMenu> sysRoleMenuList =
				sysRoleMenuMapper.selectList(Wrappers.<SysRoleMenu>lambdaQuery().eq(SysRoleMenu::getRoleId, roleId));
		//转换给角色id与角色权限对应Map对象
		List<Long> menuIdList = sysRoleMenuList.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList());
		allSysMenuList.forEach(e -> e.setSelect(menuIdList.contains(e.getId())));
		//构建树形数据
		return MenuHelper.buildTree(allSysMenuList);
	}
	
	/**
	 * 给角色分配权限
	 */
	@Transactional
	@Override
	public void doAssign(AssignMenuVo assignMenuVo) {
		List<Long> menuIdList = assignMenuVo.getMenuIdList();
		if (assignMenuVo.getRoleId() == null || menuIdList == null || menuIdList.isEmpty()) {
			log.error("【分配菜单】参数错误");
			throw new SystemException(HttpConstant.CODE_400, GlobalConstant.PARAMETER_ERROR);
		}
		sysRoleMenuMapper.delete(Wrappers.<SysRoleMenu>lambdaQuery().eq(SysRoleMenu::getRoleId,
				assignMenuVo.getRoleId()));
		// 批量插入
		menuIdList.forEach(e -> {
			if (e != null) {
				sysRoleMenuMapper.insert(SysRoleMenu.builder().roleId(assignMenuVo.getRoleId()).roleId(e).build());
			}
		});
	}
	
	/**
	 * 获取菜单权限数据
	 */
	@Override
	public List<RouterVo> findUserMenuList(Long userId) {
		//超级管理员admin账号id为：1
		List<SysMenu> sysMenuList = null;
		if (userId.equals(GlobalConstant.LONG_ONE)) {
			sysMenuList =
					list(Wrappers.<SysMenu>lambdaQuery().eq(SysMenu::getStatus, GlobalConstant.INTEGER_ONE).orderByAsc(SysMenu::getSortValue));
		} else {
			sysMenuList = sysMenuMapper.findListByUserId(userId);
		}
		//构建树形数据
		return buildMenus(MenuHelper.buildTree(sysMenuList));
	}
	
	/**
	 * 根据菜单构建权限
	 */
	@Override
	public List<String> findUserPermsList(Long userId) {
		//超级管理员admin账号id为：1
		List<SysMenu> sysMenuList = null;
		if (userId.equals(GlobalConstant.LONG_ONE)) {
			sysMenuList = list(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getStatus, GlobalConstant.INTEGER_ONE));
		} else {
			sysMenuList = sysMenuMapper.findListByUserId(userId);
		}
		return sysMenuList.stream().filter(e -> e.getType().equals(GlobalConstant.INTEGER_TWO)).map(SysMenu::getPerms).collect(Collectors.toList());
	}
	
	/**
	 * 根据菜单构建路由
	 */
	private List<RouterVo> buildMenus(List<SysMenu> menus) {
		List<RouterVo> routers = new LinkedList<>();
		menus.forEach(menu -> {
			RouterVo router =
					RouterVo.builder().hidden(false).alwaysShow(false).path(getRouterPath(menu)).component(menu.getComponent()).meta(new MetaVo(menu.getName(), menu.getIcon())).build();
			List<SysMenu> children = menu.getChildren();
			//如果当前是菜单，需将按钮对应的路由加载出来，如：“角色授权”按钮对应的路由在“系统管理”下面
			if (menu.getType().equals(GlobalConstant.INTEGER_ONE)) {
				children.stream().filter(item -> !StringUtils.isEmpty(item.getComponent())).forEach(e -> routers.add(RouterVo.builder().hidden(true).alwaysShow(false).path(getRouterPath(e)).component(e.getComponent()).meta(new MetaVo(e.getName(), e.getIcon())).build()));
			} else {
				if (!CollectionUtils.isEmpty(children)) {
					router.setAlwaysShow(true);
					router.setChildren(buildMenus(children));
				}
			}
			routers.add(router);
		});
		return routers;
	}
	
	/**
	 * 获取路由地址
	 */
	public String getRouterPath(SysMenu menu) {
		String routerPath = "/" + menu.getPath();
		if (menu.getParentId().equals(GlobalConstant.LONG_ZERO)) {
			routerPath = menu.getPath();
		}
		return routerPath;
	}
}